﻿namespace ADOGuy
{
    using Microsoft.CSharp;
    using System;
    using System.CodeDom.Compiler;
    using System.Text;

    public class Evaluator
    {
        private object _object;
        private const string staticMethodName = "__foo";

        public Evaluator(EvaluatorItem[] evItem)
        {
            this.GetEvaluator(evItem);
        }

        public Evaluator(EvaluatorItem evItem)
        {
            EvaluatorItem[] itemArray = new EvaluatorItem[] { evItem };
            this.GetEvaluator(itemArray);
        }

        public Evaluator(Type type, string expression, string name)
        {
            EvaluatorItem[] evItem = new EvaluatorItem[] { new EvaluatorItem(type, expression, name) };
            this.GetEvaluator(evItem);
        }

        public object Evaluate(string str)
        {
            return this._object.GetType().GetMethod(str).Invoke(this._object, null);
        }

        public bool EvaluateBool(string str)
        {
            return (bool) this.Evaluate(str);
        }

        public int EvaluateInt(string str)
        {
            return (int) this.Evaluate(str);
        }

        public string EvaluateString(string str)
        {
            return (string) this.Evaluate(str);
        }

        public static bool EvaluateToBool(string str)
        {
            Evaluator evaluator = new Evaluator(typeof(bool), str, "__foo");
            return (bool) evaluator.Evaluate("__foo");
        }

        public static int EvaluateToInteger(string str)
        {
            Evaluator evaluator = new Evaluator(typeof(int), str, "__foo");
            return (int) evaluator.Evaluate("__foo");
        }

        public static object EvaluateToObject(string str)
        {
            Evaluator evaluator = new Evaluator(typeof(object), str, "__foo");
            return evaluator.Evaluate("__foo");
        }

        public static string EvaluateToString(string str)
        {
            Evaluator evaluator = new Evaluator(typeof(string), str, "__foo");
            return (string) evaluator.Evaluate("__foo");
        }

        private void GetEvaluator(EvaluatorItem[] evItem)
        {
            ICodeCompiler compiler = new CSharpCodeProvider().CreateCompiler();
            CompilerParameters options = new CompilerParameters();
            options.ReferencedAssemblies.Add("system.dll");
            options.ReferencedAssemblies.Add("system.data.dll");
            options.ReferencedAssemblies.Add("system.xml.dll");
            options.GenerateExecutable = false;
            options.GenerateInMemory = true;
            StringBuilder builder = new StringBuilder();
            builder.Append("using System; \n");
            builder.Append("using System.Data; \n");
            builder.Append("using System.Data.SqlClient; \n");
            builder.Append("using System.Data.OleDb; \n");
            builder.Append("using System.Xml; \n");
            builder.Append("namespace ADOGuy { \n");
            builder.Append("  public class _Evaluator { \n");
            foreach (EvaluatorItem item in evItem)
            {
                builder.AppendFormat("    public {0} {1}() ", item.ReturnType.Name, item.Name);
                builder.Append("{ ");
                builder.AppendFormat("      return ({0}); ", item.Expression);
                builder.Append("}\n");
            }
            builder.Append("} }");
            CompilerResults results = compiler.CompileAssemblyFromSource(options, builder.ToString());
            if (results.Errors.HasErrors)
            {
                StringBuilder builder2 = new StringBuilder();
                builder2.Append("Error Compiling Expression: ");
                foreach (CompilerError error in results.Errors)
                {
                    builder2.AppendFormat("{0}\n", error.ErrorText);
                }
                throw new Exception("Error Compiling Expression: " + builder2.ToString());
            }
            this._object = results.CompiledAssembly.CreateInstance("ADOGuy._Evaluator");
        }
    }
}

